<?php defined('SYSPATH') OR die('No direct access allowed.');

class WB_Menu {
	
	private $parent = null;
	private $children = array();
	private $indent = 0;
	
	private $title;
	private $url = '';
	private $translate = FALSE;
	
	private $selected = FALSE;
	private $sub_selected = FALSE;
	
	private $html_prefix = '';
	private $html_suffix = '';
	private $container_attr = array();
	private $anchor_attr = array();
	
	private $mod = 'basic';
	

	/**
	 * Creates a new menu item with its title
	 *
	 * @param   string  title of the menu item
	 * @param   int indent
	 * @return  void
	 */
	public function __construct($title='', $indent=0)
	{
		$this->title = $title;
		$this->indent = $indent;
		
		$this->mod = Kohana::config('admin.navigation_mod');
	}

	/**
	 * Creates and returns a new menu item.
	 *
	 * @chainable
	 * @param   string  menu item title
	 * @param   int indent
	 * @return  WB_Menu
	 */
	public static function factory($title, $indent)
	{
		return new WB_Menu($title, $indent);
	}
	
	/**
	 * Url setter
	 * 
	 * @chainable
	 * @param string $url
	 * @return void
	 */
	public function set_url($url)
	{
		$this->url = $url;
		
		return $this;
	}
	
	/**
	 * Translate setter
	 * 
	 * @chainable
	 * @param boolean $translate
	 * @return void
	 */
	public function set_translate($translate)
	{
		$this->translate = $translate;
		
		return $this;
	}
	
	/**
	 * Prefix setter
	 * 
	 * @chainable
	 * @param boolean $translate
	 * @return void
	 */
	public function set_prefix($html)
	{
		$this->html_prefix = $html;
		
		return $this;
	}
	
	/**
	 * Suffix setter
	 * 
	 * @chainable
	 * @param boolean $translate
	 * @return void
	 */
	public function set_suffix($html)
	{
		$this->html_suffix = $html;
		
		return $this;
	}
	
	/**
	 * Container attribute setter
	 * 
	 * @chainable
	 * @param mixed attributes or attribute key
	 * @param mixed null or attribute value
	 * @return void
	 */
	public function set_container_attr($key, $val)
	{
		if (is_array($key)) foreach ($key as $k=>$v) $this->container_attr[$k] = $v;
		else $this->container_attr[$key] = $val;
		
		return $this;
	}
	
	/**
	 * Anchor attribute setter
	 * 
	 * @chainable
	 * @param mixed attributes or attribute key
	 * @param mixed null or attribute value
	 * @return void
	 */
	public function set_anchor_attr($key, $val)
	{
		if (is_array($key)) foreach ($key as $k=>$v) $this->anchor_attr[$k] = $v;
		else $this->anchor_attr[$key] = $val;
		
		return $this;
	}
	
	/**
	 * Builds a new menu from an array;
	 * 
	 * @param array $struct
	 * @param boolean $translate
	 * @return WB_Menu
	 */
	public function build($struct, $translate=FALSE)
	{
		$this->translate = $translate;
		foreach ($struct as $k=>$v)
		{
			if (is_array($v)) $this->children[] = WB_Menu::factory($k, $this->indent+1)->build($v, $translate);
			else $this->children[] = WB_Menu::factory($k, $this->indent+1)->set_url($v)->set_translate($translate);
		}
		return $this;
	}
	
	/**
	 * Select menu items
	 * 
	 * @param mixed $url
	 * @return int $selected_num
	 */
	public function select($url)
	{
		
		if (is_array($url) && in_array($this->url, $url) || is_string($url) && $this->url==$url) 
		{
			$this->selected = TRUE;
			$selected_num = 1;
		}
		else $selected_num = 0;
		
		foreach ($this->children as $child) $selected_num += $child->select($url);
		if ( ! $this->selected && $selected_num>0) $this->sub_selected = TRUE;
		
		return $selected_num;
	}
	
	/**
	 * Find menu items
	 * 
	 * @param mixed $url
	 * @return array
	 */
	public function find($url)
	{
		$found = array();
		if (is_array($url) && in_array($this->url, $url) || is_string($url) && $this->url==$url) $found[] = $this;
		
		foreach ($this->children as $child) $found += $child->find($url);
		
		return $found;
	}
	
	/**
	 * Renders the menu
	 * 
	 * @return string
	 */
	public function render()
	{
		$indent = str_repeat('	', $this->indent);
		
		$html = '';
		$html .= $indent.'		'.$this->item_html();
		if ( ! empty($this->children))
		{
			$html .= $indent."<ul>\n";
			foreach ($this->children as &$child)
			{
				$html .= $indent.'	'.$child->li_open();
				$html .= $child->render();
				$html .= $indent.'	'.$child->li_close();
			}
			$html .= $indent."</ul>\n";
		}
		
		return $html;
	}
	
	private function item_html()
	{
		return $this->indent==0 ? $this->item_html_basic() : call_user_func(array($this, 'item_html_'.$this->mod));
	}
	
	private function li_open()
	{
		return $this->indent==0 ? $this->li_open_basic() : call_user_func(array($this, 'li_open_'.$this->mod));
	}
	
	private function li_close()
	{
		return $this->indent==0 ? $this->li_close_basic() : call_user_func(array($this, 'li_close_'.$this->mod));
	}
	
	/**
	 * Renders the menu item (default version)
	 * 
	 * @return string
	 */
	private function item_html_basic()
	{
		$title = $this->translate ?
					Kohana::lang('wb_menu.'.$this->title) :
					$this->title;
					
		return empty($title) ? 
					'' :
					(
						empty($this->url) ?
						'<span>'.$title.'</span>' :
						$this->html_prefix.html::anchor($this->url,$title,$this->anchor_attr).$this->html_suffix
					);
	}
	
	private function li_open_basic()
	{
		if (empty($this->title)) return '';
		
		if ($this->selected)
			$this->container_attr['class'] = 
					isset($this->container_attr['class']) ? 
						$this->container_attr['class'].' selected' : 
						'selected';

		elseif ($this->sub_selected) 
			$this->container_attr['class'] = 
					isset($this->container_attr['class']) ?
						$this->container_attr['class'].' sub_selected' :
						'sub_selected';
		
		return '<li '.html::attributes($this->container_attr).">\n";
	}
	
	private function li_close_basic()
	{
		if (empty($this->title)) return '';
		
		return "</li>\n";
	}
	
	
	
	/**
	 * Renders the menu item (ie version)
	 * 
	 * @return string
	 */
	private function item_html_ie()
	{
		$title = $this->translate ?
					Kohana::lang('wb_menu.'.$this->title) :
					$this->title;
					
		return '<a href="'.($this->url ? url::site($this->url) : '#').'">'.$title.'<!--[if IE 7]><!--></a><!--<![endif]-->
<!--[if lte IE 6]><table><tr><td><![endif]-->';
	}
	
	private function li_open_ie()
	{
		return $this->li_open_basic();
	}
	
	private function li_close_ie()
	{
		if (empty($this->title)) return '';
		
		return '<!--[if lte IE 6]></td></tr></table></a><![endif]-->'."</li>\n";
	}

	/**
	 * Magically converts menu object to string.
	 *
	 * @return  string
	 */
	public function __toString()
	{
		try
		{
			return $this->render();
		}
		catch (Exception $e)
		{
			// Display the exception using its internal __toString method
			return (string) $e;
		}
	}
	
	
}

//End of WB_Menu Library